package org.ysling.litemall.db.mybatis;

import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.beust.jcommander.internal.Lists;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.List;
import java.util.Objects;

/**
 * 多租户处理插件
 */
public class CustomTenantLineHandler implements TenantLineHandler {

    private static final String TENANT_ID = "X-Litemall-TenantId";

    /**
     * 默认租户
     */
    private static final Integer DEFAULT_TENANT_ID = 0;

    /**
     * 租户ID
     */
    private static Integer tenantId = 0;

    /**
     * 获取租户ID
     */
    public static Integer getByTenantId(){
        return tenantId;
    }

    /**
     * 忽略添加租户ID的表
     */
    private static final List<String> IGNORE_TABLE_NAMES = Lists.newArrayList(
            "litemall_tenant","litemall_admin","litemall_permission","litemall_region","litemall_role"
    );

    /**
     * 获取租户 ID 值表达式，只支持单个 ID 值
     * <p>
     *
     * @return 租户 ID 值表达式
     */
    @Override
    public Expression getTenantId() {
        CustomTenantLineHandler.tenantId = DEFAULT_TENANT_ID;

        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (Objects.isNull(sra)){
            return new LongValue(DEFAULT_TENANT_ID);
        }
        String tenantId = WebUtils.toHttp(sra.getRequest()).getHeader(TENANT_ID);
        if (Objects.isNull(tenantId)){
            return new LongValue(DEFAULT_TENANT_ID);
        }

        CustomTenantLineHandler.tenantId = Integer.parseInt(tenantId);
        return new LongValue(tenantId);
    }

    /**
     * 获取租户字段名
     * <p>
     * 默认字段名叫: tenant_id
     *
     * @return 租户字段名
     */
    @Override
    public String getTenantIdColumn() {
        return "tenant_id";
    }

    /**
     * 根据表名判断是否忽略拼接多租户条件
     * <p>
     * 默认都要进行解析并拼接多租户条件
     *
     * @param tableName 表名
     * @return 是否忽略, true:表示忽略，false:需要解析并拼接多租户条件
     */
    @Override
    public boolean ignoreTable(String tableName) {
        //租户ID为零则忽略所有表
        if(tenantId.equals(DEFAULT_TENANT_ID)){
            return true;
        }
        return IGNORE_TABLE_NAMES.contains(tableName);
    }

}
